#include "speechengine.h"

bool festivalIsRuning()
{
    QTcpSocket socket;
    socket.connectToHost(QHostAddress::LocalHost,1314);
    if (!socket.waitForConnected(100)) {
            //wait;
            return false;
    }
    return true;
}

festivalStarter::festivalStarter(QObject *parent) :
    QObject(parent)
{
    festivalSrv = new QProcess(this);
    if (!festivalIsRuning()) {
        festivalSrv->start("festival --server --language russian");
    }
}

festivalStarter::~festivalStarter()
{
    if (festivalSrv->isOpen())
        festivalSrv->close();
}

speechengine::speechengine(QObject *parent) :
    QThread(parent)
{
    speeshPipeline = 0;
}

speechengine::~speechengine()
{
}

void speechengine::run() {
    while (!festivalIsRuning()) {
        QEventLoop loop; QTimer::singleShot(400, &loop, SLOT(quit())); loop.exec();
    }
}

void speechengine::speechText(QByteArray textToSpeech,int volume) {

    GstCaps *caps;
    GstBuffer *buffer;
    GstFlowReturn ret;

    gst_init (0, 0);

    if (speeshPipeline) {
        gst_element_set_state (speeshPipeline, GST_STATE_NULL);
        gst_object_unref (GST_OBJECT (speeshPipeline));
    }

    speeshPipeline = gst_pipeline_new ("speechpipe");

    speechSource   = gst_element_factory_make("appsrc", "source");
    g_object_set(G_OBJECT(speechSource), "stream-type", 0, NULL);

    caps = gst_caps_new_simple ("text/plain", NULL);
    gst_app_src_set_caps(GST_APP_SRC(speechSource), caps);
    gst_caps_unref (caps);

    festival = gst_element_factory_make ("festival", "s_festival");
    if (festival == NULL)
        return;

    wavparse = gst_element_factory_make ("wavparse", "s_wavparse");
    if (wavparse == NULL)
        return;

    audioconvert = gst_element_factory_make ("audioconvert", "s_audioconvert");
    if (audioconvert == NULL)
        return;

    speechVolume = gst_element_factory_make ("volume", "s_volume");
    if (speechVolume == NULL)
        return;
    g_object_set ( G_OBJECT (speechVolume), "volume", (double)volume / 100, NULL);

    speechAmp = gst_element_factory_make ("audioamplify", "s_amp");
    if (speechAmp == NULL)
        return;

    float amp = 1.5;
    g_object_set ( G_OBJECT (speechAmp), "amplification", amp, NULL);

    speechSink = gst_element_factory_make ("alsasink", "s_sink");
    if (speechSink == NULL)
        return;

    gst_bin_add_many (GST_BIN (speeshPipeline), speechSource, festival, wavparse, audioconvert, speechVolume, speechAmp, speechSink, NULL);

    gst_element_link_many (speechSource, festival, wavparse, NULL);

    g_signal_connect(wavparse, "pad-added",
                       G_CALLBACK (new_pad), (gpointer) audioconvert);

    gst_element_link_many (audioconvert, speechVolume, speechAmp, speechSink, NULL);

    gst_element_set_state (speeshPipeline, GST_STATE_PLAYING);

    buffer = gst_buffer_new ();
    GST_BUFFER_DATA (buffer) = textToSpeech.data();
    GST_BUFFER_SIZE (buffer) = textToSpeech.length();
    g_signal_emit_by_name (speechSource, "push-buffer", buffer, &ret);
    gst_buffer_unref (buffer);
    g_signal_emit_by_name (speechSource, "end-of-stream", &ret);

}

void speechengine::new_pad (GstElement *element,
         GstPad     *pad,
         gpointer    data)
{
  GstPad *sinkpad;

  GstElement *sink = (GstElement*) data;
  sinkpad = gst_element_get_pad (sink, "sink");
  gst_pad_link (pad, sinkpad);

  gst_object_unref (sinkpad);
}
